/**
 * 文件名：@ValidationInterceptor.java <br/>
 * 包名：cn.efunbox.afw.web.mvc.interceptor <br/>
 * 项目名：afw-mvc-web <br/>
 * @author xtwin <br/>
 */
package cn.efunbox.afw.web.mvc.interceptor;

import java.util.Map;

import org.springframework.web.method.HandlerMethod;

import cn.efunbox.afw.core.annotation.mvc.Validate;
import cn.efunbox.afw.core.bean.PropertyEditor;
import cn.efunbox.afw.core.mvc.context.Context;
import cn.efunbox.afw.core.regulation.ExpressionExecutor;
import cn.efunbox.afw.core.util.StringUtil;

/**
 * 类名：ValidationInterceptor  <br />
 *
 * 功能：校验拦截器，用于切入校验机制
 *
 * @author xtwin <br />
 * 创建时间：2015年12月2日 下午6:27:40  <br />
 * @version 2015年12月2日
 */
public class ValidationInterceptor extends AbstractInterceptor {
	
	// 表达式执行器
	private ExpressionExecutor expressionExecutor;
	
	// 属性编辑器，用于读取
	private PropertyEditor propertyEditor;
	
	/**
	 * 功能:提取方法上的校验注解，解析校验注解配置信息进行校验逻辑处理 <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2015年12月3日 上午11:42:38<br/>
	 * 
	 * @param context
	 * @param handler
	 * @throws Exception <br/>
	 * @see cn.efunbox.afw.web.mvc.interceptor.AbstractInterceptor#doPreHandle(cn.efunbox.afw.core.mvc.context.Context, java.lang.Object)
	 */
	@Override
	protected void doPreHandle(Context context, Object handler) throws Exception {
		if (handler instanceof HandlerMethod) {
			// 取出方法上定义的校验注解
			Validate[] validates = ((HandlerMethod) handler).getMethod().getAnnotationsByType(Validate.class);
			
			if (null != validates && validates.length > 0) {
				
				// 取出需要进行校验的数据
				Map<String, Object> root = context.getValue();
				
				// 依次对每个注解做处理
				for (Validate validate : validates) {
					
					// 优先处理常规定义，即：使用field与rule方式的定义
					String rule = validate.rule();
					
					if (! StringUtil.isEmpty(rule)) {
						// 这里不对field做非空检查
						//String field = validate.field();
						
						/*// 执行处理
						//expressionExecutor.execute(context, field, context.getValue(field), rule);
						Object value = expressionExecutor.execute(context, field, getValue(root, field), rule);
						
						// 将经过校验处理之后的数据更新到root中
						propertyEditor.setValue(root, field, value);*/
						
						// 执行校验
						validateField(context, root, validate.field(), rule);
					}
					
					// 处理复合表达式
					String[] exps = validate.value();
					
					for (String exp : exps) {
						// 这里不对index做检查，认为开发人员的代码没有问题
						int index = exp.indexOf(':');
						
						String field = exp.substring(0, index);
						rule = exp.substring(index + 1);
						
						/*// 交给表达式执行处理
						// expressionExecutor.execute(context, field, context.getValue(field), rule);
						Object value = expressionExecutor.execute(context, field, getValue(root, field), rule);
						
						// 将经过校验处理之后的数据更新到root中
						propertyEditor.setValue(root, field, value);*/
						
						// 执行校验
						validateField(context, root, field, rule);
					}
				}
			}
		}
	}
	
	/**
	 * 
	 * 功能：使用指定的rule校验root中的field字段 <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2015年12月8日 下午12:17:01 <br/>
	 */
	protected void validateField(Context context, Map<String, Object> root, String field, String rule) throws Exception {
		
		Object oldValue = null;
		boolean direct = false;
		if (root.containsKey(field)) {
			// 若map中包含该字段，则直接从map中提取该字段的值
			oldValue = root.get(field);
			
			direct = true;
		} else {
			/**
			 * 若map不是直接包含，则尝试使用属性导航的方式去root中提取
			 * 如：user.name
			 */
			oldValue = propertyEditor.getValue(root, field);
		}
		
		//expressionExecutor.execute(context, field, context.getValue(field), rule);
		Object newValue = expressionExecutor.execute(context, field, oldValue, rule);
		
		if (newValue != oldValue) {
			if (direct) {
				//context.setValue(field, newValue);
				root.put(field, newValue);
			} else {
				// 将经过校验处理之后的数据更新到root中
				propertyEditor.setValue(root, field, newValue);
			}
		}
	}
	
	/**
	 * 
	 * 功能：读取字段值 <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2015年12月8日 下午12:00:58 <br/>
	 */
	protected Object getValue(Map<String, Object> root, String field) throws Exception {
		Object value = null;
		if (root.containsKey(field)) {
			value = root.get(field);
		} else {
			value = propertyEditor.getValue(root, field);
		}
		
		return value;
	}

	/**
	 * @version 2015年12月4日-下午4:19:43
	 */
	public void setExpressionExecutor(ExpressionExecutor expressionExecutor) {
		this.expressionExecutor = expressionExecutor;
	}

	/**
	 * @version 2015年12月8日-下午12:10:30
	 */
	public void setPropertyEditor(PropertyEditor propertyEditor) {
		this.propertyEditor = propertyEditor;
	}
}
